<template>
    <div class="count-to-wrapper">
        <slot name="left" />
        <p class="content-outer"><span :class="['count-to-count-text', countClass]" :id="counterId">{{ init }}</span><i
            :class="['count-to-unit-text', unitClass]">{{ unitText }}</i></p>
        <slot name="right" />
    </div>
</template>

<script>
import CountUp from 'countup';
import './styles/count-to.less';

export default {
    name: 'CountTo',
    props: {
        init: {
            type: Number,
            default: 0,
        },
        /**
         * @description 起始值，即动画开始前显示的数值
         */
        startVal: {
            type: Number,
            default: 0,
        },
        /**
         * @description 结束值，即动画结束后显示的数值
         */
        end: {
            type: Number,
            required: true,
        },
        /**
         * @description 保留几位小数
         */
        decimals: {
            type: Number,
            default: 0,
        },
        /**
         * @description 分隔整数和小数的符号，默认是小数点
         */
        decimal: {
            type: String,
            default: '.',
        },
        /**
         * @description 动画持续的时间，单位是秒
         */
        duration: {
            type: Number,
            default: 2,
        },
        /**
         * @description 动画延迟开始的时间，单位是秒
         */
        delay: {
            type: Number,
            default: 0,
        },
        /**
         * @description 是否禁用easing动画效果
         */
        uneasing: {
            type: Boolean,
            default: false,
        },
        /**
         * @description 是否使用分组，分组后每三位会用一个符号分隔
         */
        usegroup: {
            type: Boolean,
            default: false,
        },
        /**
         * @description 用于分组(usegroup)的符号
         */
        separator: {
            type: String,
            default: ',',
        },
        /**
         * @description 是否简化显示，设为true后会使用unit单位来做相关省略
         */
        simplify: {
            type: Boolean,
            default: false,
        },
        /**
         * @description 自定义单位，如[3, 'K+'], [6, 'M+']即大于3位数小于6位数的用k+来做省略
         *              1000即显示为1K+
         */
        unit: {
            type: Array,
            default() {
                return [[3, 'K+'], [6, 'M+'], [9, 'B+']];
            },
        },
        countClass: {
            type: String,
            default: '',
        },
        unitClass: {
            type: String,
            default: '',
        },
    },
    data() {
        return {
            counter: null,
            unitText: '',
        };
    },
    computed: {
        counterId() {
            return `count_to_${this._uid}`;
        },
    },
    methods: {
        getHandleVal(val, len) {
            return {
                endVal: parseInt(val / Math.pow(10, this.unit[len - 1][0]), 10),
                unitText: this.unit[len - 1][1],
            };
        },
        transformValue(val) {
            let len = this.unit.length;
            let res = {
                endVal: 0,
                unitText: '',
            };
            if (val < Math.pow(10, this.unit[0][0])) {
                res.endVal = val;
            } else {
                for (let i = 1; i < len; i++) {
                    if (val >= Math.pow(10, this.unit[i - 1][0]) && val < Math.pow(10, this.unit[i][0])) {
                        res = this.getHandleVal(val, i);
                    }
                }
            }
            if (val > Math.pow(10, this.unit[len - 1][0])) {
                res = this.getHandleVal(val, len);
            }
            return res;
        },
        getValue(val) {
            let res = 0;
            if (this.simplify) {
                let {endVal, unitText} = this.transformValue(val);
                this.unitText = unitText;
                res = endVal;
            } else {
                res = val;
            }
            return res;
        },
    },
    mounted() {
        this.$nextTick(() => {
            let endVal = this.getValue(this.end);
            this.counter = new CountUp(this.counterId, this.startVal, endVal, this.decimals, this.duration, {
                useEasing: !this.uneasing,
                useGrouping: this.useGroup,
                separator: this.separator,
                decimal: this.decimal,
            });
            setTimeout(() => {
                if (!this.counter.error) {
                    this.counter.start();
                }
            }, this.delay);
        });
    },
    watch: {
        end(newVal) {
            let endVal = this.getValue(newVal);
            this.counter.update(endVal);
        },
    },
};
</script>
